package com.bwie.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.common.constants.Constants;
import com.bwie.common.constants.TokenConstants;
import com.bwie.common.domain.RedPacket;
import com.bwie.common.domain.User;
import com.bwie.common.domain.request.RedPacketAdd;
import com.bwie.common.domain.request.RedPacketReqList;
import com.bwie.common.domain.request.SnatchRedPacketSuccessQueueReq;
import com.bwie.common.domain.response.RedPacketVo;
import com.bwie.common.exceptions.BizException;
import com.bwie.common.result.Result;
import com.bwie.common.utils.JwtUtils;
import com.bwie.system.init.InitSnatchMsgToEs;
import com.bwie.system.mapper.RedPacketMapper;
import com.bwie.system.service.RedPacketService;
import com.bwie.system.service.UserService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.Console;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author Junchen_N1
 * @Date 2025/6/17 13:47
 * @ClassName RedPacketServiceImpl
 * @Description TODO
 */
@Service
public class RedPacketServiceImpl extends ServiceImpl<RedPacketMapper, RedPacket> implements RedPacketService {

    @Autowired
    private RedPacketMapper redPacketMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private InitSnatchMsgToEs initSnatchMsgToEs;

    @Autowired
    private Redisson redisson;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 红包列表
     * @param redPacketReqList
     * @return
     */
    @Override
    public Result<List<RedPacketVo>> selectRedPacketList(RedPacketReqList redPacketReqList) {
        //不展示已过期，已被抢完，不展示可领取人不是当前用户
        List<RedPacketVo> redPacketVoList = redPacketMapper.selectRedPacketList(redPacketReqList);

        //获取当前登录用户信息
        Integer loginUserId = getLoginUserMsg().getUserId();

        List<RedPacketVo> redPacketVos = new ArrayList<>();

        //过滤出当前用户无法看到的数据
        redPacketVoList.forEach(item -> {
            String canReceiveUserIds = item.getCanReceiveUserIds();
            String[] split = canReceiveUserIds.split(",");
            int isCanSee = -1;
            for (String id : split) {
                if (Integer.valueOf(id).equals(loginUserId)) {
                    isCanSee = 1;
                    break;
                }
            }
            if (isCanSee != -1) {
                redPacketVos.add(item);
            }
        });
        return Result.success(redPacketVos);
    }

    /**
     * 发红包
     * @param redPacketAdd
     */
    @Transactional
    @Override
    public void addRedPacket(RedPacketAdd redPacketAdd) {
        //红包金额不超过当前用户的账户余额
        User user = userService.findById(getLoginUserMsg().getUserId());
        //如果红包金额大于用户账户金额，抛异常
        if (redPacketAdd.getRedPacketPrice().compareTo(user.getBalance()) > 0) {
            throw new BizException("红包金额不超过当前用户的账户余额");
        }
        if (redPacketAdd.getRedPacketNums() <= 0 || redPacketAdd.getRedPacketNums() > redPacketAdd.getCanReceiveUserIdsList().size()) {
            throw new BizException("用户设置的红包个数必须大于0，并且不能超过允许抢红包的好友数量");
        }

        redPacketAdd.setCanReceiveUserIds(getString(redPacketAdd));
        //添加红包列表
        RedPacket redPacket = new RedPacket();
        BeanUtils.copyProperties(redPacketAdd, redPacket);
        redPacket.setSenderId(getLoginUserMsg().getUserId());
        redPacket.setSendTime(new Date());
        redPacket.setRedPacketRemainPrice(redPacketAdd.getRedPacketPrice());
        redPacketMapper.insert(redPacket);


        //扣减用户余额
        userService.updateUserBalance(user.getUserId(), redPacketAdd.getRedPacketPrice(), Constants.SUB_BALANCE);
    }

    /**
     * 查询所有状态为正常的红包，让定时器做轮询检测
     * @return
     */
    @Override
    public List<RedPacket> selectAllWhereStatusIs0() {
        LambdaQueryWrapper<RedPacket> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RedPacket::getRedPacketStatus, 0);
        return redPacketMapper.selectList(queryWrapper);
    }

    /**
     * 抢红包
     * @param redPacketId
     */
    @Transactional
    @Override
    public void snatchRedPacket(Integer redPacketId) {
        //判断当前用户是否抢过该红包
        Integer userId = getLoginUserMsg().getUserId();
        Integer count = userService.findByIdOfUserRedPacketReceive(userId,redPacketId);
        if (count!=0){
            throw new BizException("红包不可以重复抢哦");
        }
        RLock lock = redisson.getLock(Constants.SNATCH_RED_PACKET_KEY + redPacketId);
        lock.lock();
        try {
            BigDecimal snatchPrice = new BigDecimal(0);
            RedPacket redPacket = redPacketMapper.selectById(redPacketId);
            if (redPacket.getReceivedNums()>=redPacket.getRedPacketNums()){
                throw new BizException("红包已抢完");
            }
            if (redPacket.getRedPacketStatus()==1){
                throw new BizException("红包已结束");
            }
            if (redPacket.getRedPacketRemainPrice().divide(new BigDecimal(redPacket.getRedPacketNums() - redPacket.
                    getReceivedNums())).compareTo(new BigDecimal("0.01")) == 0) {
                snatchPrice = new BigDecimal("0.01");
            }else {
                //总金额/剩余人数
                BigDecimal divide = redPacket.getRedPacketRemainPrice().divide(new BigDecimal(redPacket.getRedPacketNums() - redPacket.
                        getReceivedNums()));
                //0.01*(剩余人数-1)
                BigDecimal multiply = new BigDecimal("0.01").multiply((new BigDecimal(redPacket.getRedPacketNums() - redPacket.
                        getReceivedNums()).subtract(new BigDecimal(1))));
                snatchPrice = divide.subtract(multiply);
            }

            //更新红包表
            LambdaUpdateWrapper<RedPacket> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(RedPacket::getRedPacketId,redPacket.getRedPacketId());
            updateWrapper.set(RedPacket::getReceivedNums,redPacket.getReceivedNums()+1);
            BigDecimal subtract = redPacket.getRedPacketRemainPrice().subtract(snatchPrice);
            updateWrapper.set(RedPacket::getRedPacketRemainPrice,subtract);
            redPacketMapper.update(updateWrapper);

            //修改用户余额
            userService.updateUserBalance(getLoginUserMsg().getUserId(),snatchPrice,Constants.ADD_BALANCE);

            //添加抢红包记录表
            userService.addRedPacketReceived(redPacketId,redPacket.getRedPacketName(),getLoginUserMsg().getUserId(),getLoginUserMsg().getUsername(),snatchPrice);

            //异步发送通知
            SnatchRedPacketSuccessQueueReq snatchRedPacketSuccessQueueReq = new SnatchRedPacketSuccessQueueReq();
            snatchRedPacketSuccessQueueReq.setPrice(snatchPrice);
            snatchRedPacketSuccessQueueReq.setTel(getLoginUserMsg().getTel());
            snatchRedPacketSuccessQueueReq.setUuid(UuidUtils.generateUuid());
            rabbitTemplate.convertAndSend(Constants.SNATCH_SUCCESS_QUEUE,snatchRedPacketSuccessQueueReq);
        } finally {
            lock.unlock();
        }

        //重新同步es
        initSnatchMsgToEs.initSnatchMsgToEs();
    }


    private String getString(RedPacketAdd redPacketAdd) {
        if (redPacketAdd.getRedPacketPrice().divide(new BigDecimal(String.valueOf(redPacketAdd.getRedPacketNums()))).compareTo(new BigDecimal("0.01")) <= 0) {
            throw new BizException("每个红包的最小金额需大于0.01元");
        }

        List<Integer> canReceiveUserIdsList = redPacketAdd.getCanReceiveUserIdsList();
        canReceiveUserIdsList.add(getLoginUserMsg().getUserId());
        StringBuffer stringBuffer = new StringBuffer();
        canReceiveUserIdsList.forEach(item -> {
            stringBuffer.append(item).append(",");
        });

        return stringBuffer.substring(0, stringBuffer.toString().length() - 1);
    }


    private User getLoginUserMsg() {
        String token = request.getHeader(TokenConstants.TOKEN);
        String userKey = JwtUtils.getUserKey(token);
        User loginUser = (User) redisTemplate.opsForValue().get(TokenConstants.LOGIN_TOKEN_KEY + userKey);
        if (ObjectUtil.isEmpty(loginUser)) {
            throw new BizException("用户信息已过期");
        }
        return loginUser;
    }


    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        System.out.println(JSON.toJSONString(list));
    }
}
